<template>
    <div class="public-vulnerability-select-drawer">
        <div class="check-tab" :class="multiple ? '' : 'not-multiple'" @click="showDrawer">
            <div v-show="selectVulnerabilityList.length" style="width: 100%;">
                <Tag
                    color="default"
                    v-for="item in selectVulnerabilityList"
                    :key="item.id"
                    closable
                    @click.stop
                    @on-close="removeVulnerability([], item)">{{item.name}}</Tag>
            </div>
            <span v-show="!selectVulnerabilityList.length" class="placeholder">{{ placeholder }}</span>
            <Icon type="ios-arrow-down" class="add-icon" @click.native="showDrawer" />
        </div>
        <Drawer
            :width="width"
            v-model="drawer.show"
            :transfer="transfer"
            :inner="inner"
            title="选择公共漏洞"
            class="device-drawer">
            <div class="search">
                <Input
                    clearable
                    v-model.trim="queryParams.name"
                    placeholder="漏洞名称"
                    @on-change="debounceFn"
                    style="width: 180px;margin-left: 15px;" />
                <Input
                    clearable
                    v-model.trim="queryParams.cve"
                    placeholder="CVE"
                    @on-change="debounceFn"
                    style="width: 180px;margin-left: 15px;" />
                <Input
                    clearable
                    v-model.trim="queryParams.cnnvd"
                    placeholder="CNNVD"
                    @on-change="debounceFn"
                    style="width: 180px;margin-left: 15px;" />
                <Select filterable transfer
                    v-model="queryParams.level"
                    placeholder="漏洞评级"
                    filterable
                    clearable
                    style="width:150px;text-align: left;margin-left: 15px;"
                    @on-change="changePageNow(1)">
                    <Option
                        v-for="(val, key) in $ConfigurationParameter.VULNERABILITY_LEVEL_OPTIONS"
                        :key="key"
                        :value="key"
                        :title="val">{{ val }}</Option>
                </Select>
                <Button
                    type="primary"
                    ghost
                    style="height: 32px;margin-left: 9px;"
                    @click="refreshQueryParams()">
                    <i class="el-icon-refresh-right" />
                </Button>
            </div>
            <div class="tag-group">
                <template v-if="multiple">
                    <p>已选漏洞总数: <Tag color="purple">{{selectVulnerabilityList.length }}</Tag></p>
                    <div class="tag-group-1">
                        <Tag
                            color="default"
                            v-for="item in selectVulnerabilityList"
                            :key="item.id"
                            closable
                            @on-close="removeVulnerability([], item)">{{item.name}}</Tag>
                    </div>
                </template>
                <p class="check-vulnerability" v-else>选中漏洞: <span>{{selectVulnerabilityList.length ? selectVulnerabilityList[0].name : '-' }}</span></p>
            </div>
            <Table
                border
                :columns="columns"
                :data="resData.list"
                :loading="resData.loading"
                :max-height="height"
                @on-select-all="selectVulnerability"
                @on-select="selectVulnerability"
                @on-select-all-cancel="removeVulnerability"
                @on-select-cancel="removeVulnerability"></Table>
            <Page
                :total="resData.total"
                :page-size="queryParams.pageSize"
                :current="queryParams.pageIndex"
                show-total
                show-elevator
                @on-change="changePageNow" />
        </Drawer>
    </div>
</template>

<script>
import { queryCommonVulnerabilityList } from './vulnerability.js'
import { debounce } from '@/libs/utils'

export default {
    name: 'PublicVulnerabilitySelectDrawer',
    components: {
    },
    props: {
        value: [String, Array],
        multiple: {
            type: Boolean,
            default: true
        },
        width: {
            type: Number,
            default: 60
        },
        inner: {
            type: Boolean,
            default: false
        },
        transfer: {
            type: Boolean,
            default: false
        },
        placeholder: {
            type : String,
            default: ''
        }
    },
    data() {
        return {
            resData: {
                total: 0,
                list: [],
                loading: true
            },
            columns: [
                {
                    type: 'selection',
                    width: 60,
                    align: 'center'
                },
                {
                    title: '漏洞名称',
                    key: 'name',
                    align: 'center',
                    tooltip: true,
                    width: 200,
                },
                {
                    title: '漏洞评级',
                    key: 'expType',
                    align: 'center',
                    tooltip: true,
                    render: (h, params) => {
                        let ret = this.$CodeEscape.vulnerabilityLevelEscape(params.row.level)
                        return h('Tag', {
                            props: {
                                color: ret.color
                            },
                            style: {
                                width: '60px',
                                'text-align': 'center'
                            }
                        }, ret.text)
                    }
                },
                {
                    title: '威胁评分',
                    key: 'value',
                    align: 'center',
                    tooltip: true,
                },
                {
                    title: 'CVSSV2',
                    key: 'cvssv2',
                    align: 'center',
                    tooltip: true,
                },
                {
                    title: 'CVE',
                    key: 'cve',
                    align: 'center',
                    tooltip: true,
                },
                {
                    title: 'CWE',
                    key: 'cwe',
                    align: 'center',
                    tooltip: true,
                },
                {
                    title: 'TVID',
                    key: 'tvid',
                    align: 'center',
                    tooltip: true,
                },
                {
                    title: 'CNNVD',
                    key: 'cnnvd',
                    align: 'center',
                    tooltip: true,
                }
            ],
            queryParams: {
                pageIndex: 1,
                pageSize: 20,
                name: '',
                level: '',
                cve: '',
                cnnvd: ''
            },
            drawer: {
                show: false
            },
            selectVulnerabilityList: [],
            height: 200
        }
    },
    mounted() {
        this.debounceResize = debounce(this.setTableHeight, 200);
        window.addEventListener('resize', this.debounceResize);
        if (!this.multiple) { // 单选的情况，删除全选列，添加单选操作
          let index = this.columns.findIndex(item => item.type === 'selection')
          if (index !== -1) {
            this.columns.splice(index, 1);
          }
          index = this.columns.findIndex(item => item.title === '操作')
          if (index === -1) {
            this.columns.push({
              title: '操作',
              key: 'action',
              align: 'center',
              width: 120,
              render: (h, params) => {
                let text = ''
                if(params.row._checked) {
                  text = '已选'
                } else {
                  text = '可选'
                }
                return h('a', {
                  style: {
                    color: params.row._checked ? '#2f70ff' : 'grey',
                  },
                }, [
                  h('div', {
                    on: {
                      'click': () => {
                        this.addCheck(params.row.id)
                      },
                    },
                    style: {
                    }
                  }, [
                    h('img', {
                      attrs: {
                        src: params.row._checked ? require('@/assets/globalIcon/choosed.png') : require('@/assets/globalIcon/add.png'),
                      },
                      style: {
                        'margin-right': '5px',
                        'vertical-align': 'middle',
                        width: '16px',
                        height: '16px',
                        display: 'inline-block',
                      },
                    }),
                    h('span', {}, text)
                  ])
                ])
              }
            })
          }
        }
    },
    beforeDestroy() {
        window.removeEventListener('resize', this.debounceResize);
    },
    watch: {
        value(newValue, oldValue) {
            // 值可能是字符串，也可能是数组，需要强转对比，内容无变化时不做处理
            if (String(newValue) === String(oldValue) && newValue.length === oldValue.length) {
                return
            }
        },
        selectVulnerabilityList(list) {
            this.$nextTick(() => {
                this.setTableHeight()
                if (this.isclear) { // 清空选项由父组件触发，不需要向外发送数据，避免触发了校验
                    this.isclear = false
                    return
                }
                this.$emit('input', list.map(item => item.id))
            })
        }
    },
    methods: {
        // 获取当前选中项的信息，多选时返回对象数组，单选时返回对象
        getSelectedValue() {
            if (this.selectVulnerabilityList && this.selectVulnerabilityList.length) {
                return this.selectVulnerabilityList
            } else {
                return null
            }
        },
        // 清空选中的数据
        clear() {
            this.selectVulnerabilityList = []
            this.isclear = true
        },
        // 设置表单高度
        setTableHeight() {
            let bodys = document.querySelectorAll('.device-drawer .ivu-drawer-body')
            if (bodys) {
                let height = 200
                for (let i = 0; i < bodys.length; i++) {
                    let body = bodys[i]
                    let bodyHeight = (body.clientHeight || 40) - 40 // 获取body可展示的高度，需要去掉padding的值
                    let searchHeight = body.querySelector('.search').clientHeight
                    let tagHeight = body.querySelector('.tag-group').clientHeight
                    let pageHeight = body.querySelector('.ivu-page').clientHeight
                    let diff = bodyHeight - searchHeight - tagHeight - pageHeight - 20 // 有20px的margin高度
                    height = Math.max(Math.min(Math.max(diff, 200), 1000), height) // 最低200px，最高1000px，取所有值中的最大值
                }
                this.height = height
            }
        },
        // 选中数据
        selectVulnerability(selection, row) {
            if (!row) { // 全选操作
                let checkIds = this.selectVulnerabilityList.map(item => item.id)
                selection.forEach(item => {
                    if (!checkIds.includes(item.id)) { // 未被选中的数据标记为选中，并添加到已选数组中去
                        this.addCheck(item.id)
                    }
                })
            } else {
                this.addCheck(row.id)
            }
        },
        // 移除选中数据
        removeVulnerability(selection, row){
            if(!row){ // 全选操作
                this.resData.list.forEach(item => {
                    this.removeCheck(item.id)
                })
            }else{
                this.removeCheck(row.id)
            }
        },
        // 添加选中的数据
        addCheck(id) {
            if (this.multiple) { // 支持多选
                let template = this.resData.list.find(item => item.id === id)
                if (template) {
                    template._checked = true
                }
                this.selectVulnerabilityList.push(template)
            } else {
                this.resData.list.forEach(item => {
                    if (item.id === id) {
                        item._checked = true
                        this.selectVulnerabilityList = [item]
                    } else {
                        item._checked = false
                    }
                })
            }
        },
        // 删除选中的数据
        removeCheck(id) {
            // 删除时通过下标获取数据，改变后再替换原数据，否则部分情况下，表单状态无法实时更新
            let index = this.resData.list.findIndex(item => item.id === id)
            if (index !== -1) {
                let template = this.resData.list[index]
                template._checked = false
                this.resData.list.splice(index, 1, template)
            }
            index = this.selectVulnerabilityList.findIndex(item => item.id === id)
            if (index !== -1) {
                this.selectVulnerabilityList.splice(index, 1)
            }
        },
        // 防抖方法，用于输入型查询
        debounceFn: debounce(function() {
            this.changePageNow(1);
        }),
        // 打开抽屉，初始化数据
        showDrawer() {
            this.drawer.show = true
            this.refreshQueryParams()
            this.$nextTick(() => {
                this.setTableHeight()
            })
        },
        // 重置搜索条件并查询数据
        refreshQueryParams() {
            this.queryParams = {
                pageIndex: 1,
                pageSize: 20,
                name: '',
                level: '',
                cve: '',
                cnnvd: ''
            }
            this.getCommonVulnerabilityList()
        },
        // 查询指定页数据
        changePageNow(val) {
            this.queryParams.pageIndex = val;
            this.getCommonVulnerabilityList();
        },
        // 查询公共漏洞列表
        getCommonVulnerabilityList() {
            this.resData.loading = true
            queryCommonVulnerabilityList(this.queryParams).then(({ data = {} }) => {
                let { code, message } = data
                data = data.data || {}
                if (code !== 1) {
                    this.$Message.warning(message)
                    return
                }
                let list = data.items || []
                let checkIds = this.selectVulnerabilityList.map(item => item.id)
                this.resData = {
                    total: data.total || 0,
                    list: list.map(item => {
                        item._checked = checkIds.includes(item.id)
                        return item
                    }),
                    loading: false
                }
            }).catch(() => {
                this.$Message.error('获取公共漏洞列表异常')
            }).finally(() => {
                this.resData.loading = false
            })
        },
        // 获取已选中的数据
        getCheckList(idList) {
            if (!idList) {
                return
            }
            return new Promise(resolve => {
                queryCommonVulnerabilityList({
                    pageIndex: 1,
                    pageSize: 2147483646,
                    idList
                }).then(({ data = {} }) => {
                    if (data.code === 1) {
                        this.selectVulnerabilityList = data.data.items || []
                    }
                }).finally(() => {
                    resolve()
                })
            })
        },
    }
}
</script>

<style scoped>
.public-vulnerability-select-drawer {
    width: 100%;
    height: 100%;
    position: relative;
    background: var(--select-bgcolor);
}
.device-drawer /deep/ .ivu-page {
    text-align: center;
    margin-top: 10px;
}
.search {
    display: flex;
    justify-content: flex-end;
    flex: 1;
    flex-wrap: wrap;
}
.search /deep/ .ivu-select,
.search /deep/ .ivu-input-wrapper,
.search /deep/ .ivu-date-picker,
.search /deep/ .ivu-btn,
.tag-group {
    margin-bottom: 10px;
}
.tag-group-1, .check-tab {
    display: flex;
    flex-wrap: wrap;
}
.check-tab {
  border: 1px solid var(--select-border-color) !important;
}
.check-tab:hover {
  border: 1px solid var(--select-hover-border-color) !important;
}
.add-icon:hover {
  color: var(--select-hover-border-color);
}
.tag-group-1 /deep/ .ivu-tag,
.check-tab /deep/ .ivu-tag {
    display: flex;
    justify-items: center;
    width: fit-content;
    max-width: 100%;
}
.tag-group-1 /deep/ .ivu-tag span,
.check-tab /deep/ .ivu-tag span {
    display: inline-block;
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.tag-group-1 /deep/ .ivu-tag .ivu-icon-ios-close,
.check-tab /deep/ .ivu-tag .ivu-icon-ios-close {
    top: 5px
}
.search /deep/ .ivu-input,
.search /deep/ .ivu-select-selection,
.search /deep/ .ivu-select-selection:hover,
.search /deep/ .ivu-input:hover {
    /* border: 1px solid #dcdee2 !important; */
}
.search /deep/ .ivu-select-visible .ivu-select-selection:focus,
.search /deep/ input:focus {
    /* box-shadow: 0 0 0 2px rgba(45, 140, 240, .2) !important; */
}
.search /deep/ .ivu-input-icon,
.search /deep/ .ivu-select-arrow {
    /* color: #808695 !important; */
}

.device-drawer /deep/ .ivu-drawer-mask,
.device-drawer /deep/ .ivu-drawer-wrap {
    position: fixed;
}
.check-tab {
    border: 1px solid #3a3ad1;
    border-radius: 5px;
    padding: 2px 6px;
    max-height: 200px;
    min-height: 32px;
    width: 100%;
    overflow-x: hidden;
    overflow-y: auto;
}
.check-tab.not-multiple {
    height: 34px;
}
.check-tab:focus {
    box-shadow: 0 0 0 2px rgba(45, 140, 240, .2) !important;
}
.placeholder {
    color: silver;
    line-height: 28px;
}
.add-icon {
    position: absolute;
    right: 8px;
    top: 10px;
    cursor: pointer;
}
.check-tab {
    cursor: pointer;
}
.check-tab /deep/ .ivu-tag {
  max-width: calc(100% - 20px) !important;
}
.check-vulnerability {
    width: 100%;
    display: flex;
}
.check-vulnerability span {
    max-width: calc(100% - 70px);
    display: inline-block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    margin-left: 6px;
}
</style>
